package org.simple.framework.data.jpa.query;

import org.simple.framework.data.query.ExpressionHandler;
import org.simple.framework.data.query.Match;
import org.simple.framework.data.query.MatchHandler;

import jakarta.persistence.criteria.CriteriaBuilder;

/**
 * 项目名称：simple-framework
 * 类名称：JpaExpressionHandler
 * 类描述：JpaExpressionHandler
 * 创建时间：2018/9/10
 *
 * @author sisyphus   (E-mail:1620657419@qq.com)
 * @version v1.0
 */
public class JpaExpressionHandler extends ExpressionHandler<JpaExpression> {

    private MatchHandler matchHandler;

    public JpaExpressionHandler(MatchHandler matchHandler) {
        this.matchHandler = matchHandler;
    }

    @Override
    protected JpaExpression handleEq() {
        return CriteriaBuilder::equal;
    }

    @Override
    protected JpaExpression handleNeq() {
        return CriteriaBuilder::notEqual;
    }

    @Override
    protected JpaExpression handleLike(Match match) {
        return (builder, path, value) ->
                builder.like(path, matchHandler.handle(match, value.toString()));
    }

    @Override
    protected JpaExpression handleNotLike(Match match) {
        return (builder, path, value) ->
                builder.notLike(path, matchHandler.handle(match, value.toString()));
    }

    @Override
    protected JpaExpression handleIn() {
        return (builder, path, value) -> {
            CriteriaBuilder.In<Object> in = builder.in(path);
            handleIterableValue(value).forEach(in::value);
            return in;
        };
    }

    @Override
    protected JpaExpression handleNotIn() {
        return (builder, path, value) -> {
            CriteriaBuilder.In<Object> in = builder.in(path);
            handleIterableValue(value).forEach(in::value);
            return builder.not(in);
        };
    }

    @Override
    protected JpaExpression handleGt() {
        return (builder, path, value) -> builder.greaterThan(path, (Comparable) value);
    }

    @Override
    protected JpaExpression handleLt() {
        return (builder, path, value) -> builder.lessThan(path, (Comparable) value);
    }

    @Override
    protected JpaExpression handleGte() {
        return (builder, path, value) -> builder.greaterThanOrEqualTo(path, (Comparable) value);
    }

    @Override
    protected JpaExpression handleLte() {
        return (builder, path, value) -> builder.lessThanOrEqualTo(path, (Comparable) value);
    }

    @Override
    protected JpaExpression handleIsNull() {
        return (builder, path, value) -> {
            if ((Boolean) value) {
                return builder.isNull(path);
            } else {
                return builder.isNotNull(path);
            }
        };
    }

    @Override
    protected JpaExpression handleIsNotNull() {
        return (builder, path, value) -> {
            if ((Boolean) value) {
                return builder.isNotNull(path);
            } else {
                return builder.isNull(path);
            }
        };
    }

    @Override
    protected JpaExpression handleRegex(Match match) {
        throw new UnsupportedOperationException("Jpa expression doesn't support regex operation.");
    }

}
